/*
Read pixel value from camera, store in SSRAM and display on monitor
*/
module Multi_Ports_SRAM_Ctrl	(input wire 	iSRAM_CLK,		// input clock
							input wire			iRST_N,
							input wire [17:0]	iSW,
// --SRAM interface ------
							output reg 	[18:0]	oSRAM_A,		// output address
							inout wire	[31:0]	SRAM_DQ,		// DATA INPUT and OUTPUT port
							output reg 			oSRAM_ADSC_N,	// controller address status
							output wire			oSRAM_ADSP_N,	// processor address status
							output reg			oSRAM_ADV_N,	// advance input signal (burst address advance)
							output reg 	[3:0]	oSRAM_BE_N, 	// Byte write enable
							output wire			oSRAM_CE1_N, 	// chip enable 1
							output wire			oSRAM_CE2,		// chip enable 2
							output wire 		oSRAM_CE3_N,	// chip enable 3
							output wire			oSRAM_CLK,		// clock to SRAM
							inout  wire	[3:0]	SRAM_DPA,		// Parity data
							output wire	 		oSRAM_GW_N,		// global write
							output wire			oSRAM_OE_N,		// output enable
							output wire			oSRAM_WE_N,	// write enable
							
							output reg	[7:0]	state,
//--Read Port 1
							input wire	[18:0]	r_address1,
							input wire			r_stop1,
							output wire	[31:0]	r_data1,
							output reg			r_data_avai1,
//--Read Port 2
							input wire	[18:0]	r_address2,
							input wire			r_stop2,
							output wire	[31:0]	r_data2,
							output reg			r_data_avai2,
//--Read Port 3
							input wire	[18:0]	r_address3,
							input wire			r_stop3,
							output wire	[31:0]	r_data3,
							output reg			r_data_avai3,
//--Read Port 4
							input wire	[18:0]	r_address4,
							input wire			r_stop4,
							output wire	[31:0]	r_data4,
							output reg			r_data_avai4,
//--Write Port 5
							input wire	[18:0]	w_address5,
							input wire			w_stop5,
							input wire	[31:0]	w_data5,
							input wire	[3:0]	w_BE_N5,
							output reg			w_port_avai5,
//--Write Port 6
							input wire	[18:0]	w_address6,
							input wire			w_stop6,
							input wire	[31:0]	w_data6,
							input wire	[3:0]	w_BE_N6,
							output reg			w_port_avai6,
//--Write Port 7
							input wire	[18:0]	w_address7,
							input wire			w_stop7,
							input wire	[31:0]	w_data7,
							input wire	[3:0]	w_BE_N7,
							output reg			w_port_avai7,
//--Write Port 8
							input wire	[18:0]	w_address8,
							input wire			w_stop8,
							input wire	[31:0]	w_data8,
							input wire	[3:0]	w_BE_N8,
							output reg			w_port_avai8
						);

//--SSRAM---
assign oSRAM_CLK = iSRAM_CLK;		// SRAM clock
assign oSRAM_ADSP_N = 1;			// we use ADSC_N
assign oSRAM_CE1_N	= 0;			// chip select
assign oSRAM_CE2	= 1;
assign oSRAM_CE3_N	= 0;			// chip select
assign oSRAM_GW_N	= 1;			// disable global write

reg 		SRAM_D_ena	 = 0;	// 0 read, 1 write
reg [3:0]	SRAM_DPA_out = 0;
reg [31:0]	SRAM_DW		 = 0;	// write data
reg [31:0]	SRAM_DR		 = 0;	// read data, changes at negative clock edge
assign SRAM_DPA	= SRAM_D_ena ? SRAM_DPA_out : 4'hZ;
assign SRAM_DQ 	= SRAM_D_ena ? SRAM_DW 		: 32'hZ;

//reg [7:0] 	state;	// state machine
reg [18:0] 	wp;		// write address
reg [18:0] 	rp;		// read address
assign oSRAM_OE_N	= SRAM_D_ena;
assign oSRAM_WE_N	= ~SRAM_D_ena;

assign r_data1 = SRAM_DR;
assign r_data2 = SRAM_DR;
assign r_data3 = SRAM_DR;
assign r_data4 = SRAM_DR;

always @ (posedge iSRAM_CLK) begin
	SRAM_DR	<=	SRAM_DQ;			// capture read data on the rising edge of oSRAM_CLK
end

wire [7:0] nextstate [0:5];
reg [2:0] r_ptr = 0;

assign nextstate[0] = 10;
assign nextstate[1] = 20;
assign nextstate[2] = 30;
assign nextstate[3] = 50;
assign nextstate[4] = 60;
assign nextstate[5] = 70;

always @ (posedge iSRAM_CLK or negedge iRST_N) begin
	if (!iRST_N) begin
		oSRAM_ADSC_N<= 1;
		oSRAM_ADV_N	<= 1;
		SRAM_D_ena	<= 0;
		rp			<= 0;
		wp			<= 0;
		state		<= 255;
		r_ptr		<= 0;
	end
	else begin
		case (state)
	/*	0:begin
			if (wp >= 76799) begin
				state		<=	255;
	
			end
			else begin
				state			<=	0;
				SRAM_D_ena		<=	1;				//ready for writing
				oSRAM_ADSC_N	<=	0;
				oSRAM_BE_N		<=	4'b0000;
				oSRAM_A			<=	wp;				// oSRAM_A = 0 at the first cycle
				wp				<=	wp + 1'b1;		// wp = 0 + 1;
				if 	(wp=1)
					SRAM_DW		<=	32'2526272B;
				else if (wp=2)
					SRAM_DW		<=	32'h25232728;
								
				else if (wp=2)
					SRAM_DW		<=	32'h00000000;
				else if (wp=2)
					SRAM_DW		<=	32'h00000000;										
			end
		end*/ 
		255:begin				// wait state
			 state <= nextstate[r_ptr];
			 r_ptr <= r_ptr + 1'b1;
			 if (r_ptr == 5)
				r_ptr <= 0;
		end
// Read Port 1
		10:begin
			if (r_stop1) begin
				r_data_avai1	<=	0;
				state			<=	255;
			end
			else begin
				oSRAM_ADSC_N	<= 0;	// initiate read
				SRAM_D_ena		<= 0;
				oSRAM_A			<= r_address1;
				rp				<= r_address1 + 1'b1;
				state			<= 11;
			end
		end
		11:begin					// read latency
			oSRAM_A			<= rp;
			rp				<= rp + 1'b1;
			state			<= 12;
		end
		12:begin					// read latency
			oSRAM_A			<= rp;
			rp				<= rp + 1'b1;
			if (r_stop1) begin
				r_data_avai1	<=	0;
				state			<=	255;
				end
			else begin
				r_data_avai1	<=	0;
				state			<=	13;
			end
		end
		13:begin					// read latency
			oSRAM_A			<= rp;
			rp				<= rp + 1'b1;
			if (r_stop1) begin
				r_data_avai1	<=	0;
				state			<=	255;
				end
			else begin
				r_data_avai1	<=	1;
				state			<=	13;
			end
		end
		
// Read Port 2
		20:begin
			if (r_stop2) begin
				r_data_avai2	<=	0;
				state			<=	255;
			end
			else begin
				oSRAM_ADSC_N	<= 0;	// initiate read
				SRAM_D_ena		<= 0;
				oSRAM_A			<= r_address2;
				rp				<= r_address2 + 1'b1;
				state			<= 21;
			end
		end
		21:begin					// read latency
			oSRAM_A			<= rp;
			rp				<= rp + 1'b1;
			state			<= 22;
		end
		22:begin					// read latency
			oSRAM_A			<= rp;
			rp				<= rp + 1'b1;
			if (r_stop2) begin
				r_data_avai2	<=	0;
				state			<=	255;
			end
			else begin
				r_data_avai2	<=	1;
				state			<=	22;
			end
		end
// Read Port 3
		30:begin
			if (r_stop3) begin
				r_data_avai3	<=	0;
				state			<=	255;
			end
			else begin
				oSRAM_ADSC_N	<= 0;	// initiate read
				SRAM_D_ena		<= 0;
				oSRAM_A			<= r_address3;
				rp				<= r_address3 + 1'b1;
				state			<= 31;
			end
		end
		31:begin					// read latency
			oSRAM_A			<= rp;
			rp				<= rp + 1'b1;
			state			<= 32;
		end
		32:begin					// read latency
			oSRAM_A			<= rp;
			rp				<= rp + 1'b1;
			if (r_stop3) begin
				r_data_avai3	<=	0;
				state			<=	255;
			end
			else begin
				r_data_avai3	<=	1;
				state			<=	32;
			end
		end
// Read Port 4
		40:begin
			if (r_stop4) begin
				r_data_avai4	<=	0;
				state			<=	255;
			end
			else begin
				oSRAM_ADSC_N	<= 0;	// initiate read
				SRAM_D_ena		<= 0;
				oSRAM_A			<= r_address4;
				rp				<= r_address4 + 1'b1;
				state			<= 41;
			end
		end
		41:begin					// read latency
			oSRAM_A			<= rp;
			rp				<= rp + 1'b1;
			state			<= 42;
		end
		42:begin					// read latency
			oSRAM_A			<= rp;
			rp				<= rp + 1'b1;
			if (r_stop4) begin
				r_data_avai4	<=	0;
				state			<=	255;

			end
			else begin
				r_data_avai4	<=	1;
				state			<=	42;
			end
		end
// Write port 5
		50:begin
			if (w_stop5) begin
				state			<=	255;
				w_port_avai5	<=	0;
			end
			else begin
				w_port_avai5	<=	1;
				wp				<=	w_address5;
				state			<=	51;
			end
		end
		51:begin
			if (w_stop5) begin
				state			<=	255;
				w_port_avai5	<=	0;
			end
			else begin
				SRAM_D_ena		<=	1;
				oSRAM_ADSC_N	<=	0;			// initiate write
				oSRAM_A			<=	wp;
				oSRAM_BE_N		<=	w_BE_N5;
				SRAM_DW			<=	w_data5;
				wp				<=	wp + 1'b1;
				state			<=	51;
				w_port_avai5	<=	1;
			end
		end
// Write port 6
		60:begin
			if (w_stop6) begin
				state			<=	255;
				w_port_avai6	<=	0;
			end
			else begin
				w_port_avai6	<=	1;
				wp				<=	w_address6;
				state			<=	61;
			end
		end
		61:begin
			if (w_stop6) begin
				state			<=	255;
				w_port_avai6	<=	0;
			end
			else begin
				SRAM_D_ena		<=	1;
				oSRAM_ADSC_N	<=	0;			// initiate write
				oSRAM_A			<=	wp;
				oSRAM_BE_N		<=	w_BE_N6;
				SRAM_DW			<=	w_data6;
				wp				<=	wp + 1'b1;
				state			<=	61;
				w_port_avai6	<=	1;
			end
		end
// Write port 7
		70:begin
			if (w_stop7) begin
				state			<=	255;
				w_port_avai7	<=	0;
			end
			else begin
				w_port_avai7	<=	1;
				wp				<=	w_address7;
				state			<=	71;
			end
		end
		71:begin
			if (w_stop7) begin
				state			<=	255;
				w_port_avai7	<=	0;
			end
			else begin
				SRAM_D_ena		<=	1;
				oSRAM_ADSC_N	<=	0;			// initiate write
				oSRAM_A			<=	wp;
				oSRAM_BE_N		<=	w_BE_N7;
				SRAM_DW			<=	w_data7;
				wp			<=	wp + 1'b1;
				state			<=	71;
				w_port_avai7	<=	1;
			end
		end
// Write port 8
		80:begin
			if (w_stop8) begin
				state			<=	255;
				w_port_avai8	<=	0;
			end
			else begin
				w_port_avai8	<=	1;
				wp				<=	w_address8;
				state			<=	81;
			end
		end
		81:begin
			if (w_stop8) begin
				state			<=	255;
				w_port_avai8	<=	0;
			end
			else begin
				SRAM_D_ena		<=	1;
				oSRAM_ADSC_N	<=	0;			// initiate write
				oSRAM_A			<=	wp;
				oSRAM_BE_N		<=	w_BE_N8;
				SRAM_DW			<=	w_data8;
				wp				<=	wp + 1'b1;
				state			<=	81;
				w_port_avai8	<=	1;
			end
		end
		default:begin
			state <= 255;
		end
		endcase
	end
end

endmodule